package cloudbus

import (
	"fmt"
	"time"
	"zstackgo/java"
	"zstackgo/pkg/header/message"
	"zstackgo/spring"

	"github.com/meilihao/golib/v2/log"
	"github.com/patrickmn/go-cache"
)

var (
	_ DeadMessageManager = new(DeadMessageManagerImpl)
)

func init() {
	o := new(DeadMessageManagerImpl)
	spring.Register(o, "DeadMessageManager", []*spring.PluginExtension{
		{
			Interface: "header.Component",
			Order:     999,
		},
		{
			Interface: "header.managementnode.ManagementNodeChangeListener",
		},
	})
}

type DeadMessageManagerImpl struct {
	managementNodeNotFoundHandlers  *cache.Cache
	previousOfflinedManagementNodes *cache.Cache
}

func NewDeadMessageManagerImpl() *DeadMessageManagerImpl {
	impl := &DeadMessageManagerImpl{}

	impl.previousOfflinedManagementNodes = cache.New(30*time.Minute, 10*time.Minute)
	return impl
}

func (impl *DeadMessageManagerImpl) HandleManagementNodeNotFoundError(managementNodeUuid string, message message.Message, rsendFun java.Runnable) bool {
	if rsendFun == nil {
		panic("rsendFunc cannot be null")
	}

	if _, ok := impl.previousOfflinedManagementNodes.Get(managementNodeUuid); !ok {
		// the node never gets online, no need to handle this message
		return false
	}

	log.Glog.Debug(fmt.Sprintf("save message[uuid:%s] to offline-node[uuid:%s] for later delivery, managementNodeNotFoundHandlers has N entries. %s",
		message.GetId(), managementNodeUuid, dumpMessage(message)))

	handler := &ManagementNodeNotFoundHandler{
		ManagementNodeUuid: managementNodeUuid,
		Message:            message,
		ResendFunc:         rsendFun,
	}
	impl.managementNodeNotFoundHandlers.SetDefault(PlatformGetManagementServerId(), handler)

	return true
}

type ManagementNodeNotFoundHandler struct {
	ResendFunc         java.Runnable
	Message            message.Message
	ManagementNodeUuid string
}

func (h ManagementNodeNotFoundHandler) Handle() {
	h.ResendFunc.Run()

	log.Glog.Debug(fmt.Sprintf("successfully resend the message[id:%s] to a previous-offline management node[uuid:%s]",
		h.Message.GetId(), h.ManagementNodeUuid))
}
